/**
 * 配置面板的mixin 文件，
 *
 * 有特殊情况就覆写方法
 */
import configMerge from '@/utils/config-merge.js';
import { EMIT_PARAMS_OBJ } from '@/utils/constant';
import { $message, isPromise, visualAction, clone, isArray, isObject, bindVisibleChange } from '@/utils/util';
import { mapMutations, mapState } from 'vuex';
import BasicMixin from '@/mixin/base-mixin.js';
import EventBus from '@/event-bus/EventBus.js';
import VsFormItem from '@/components/common/vs-form-item/vs-form-item.vue';

export default {
  emits: [],
  mixins: [BasicMixin],
  props: {
    config: Object,
    dbConfig: Object,
    orgConfig: Object,
    widgetInstanceId: String,
    widget: Object,
    isChildComponent: { type: Boolean, default: false }, // 是否子组件
  },
  data() {
    return {
      xvueNameSpace: process.env.xvueNameSpace, // 在配置面板的mixin文件里声明这个变量，用于给所有组件的配置面板加上主类名
      xvueTheme: window._adoPremise.uc.theme,
      isCanSave: true, // 是否能够满足保存条件
      panelConfigTimer: null,
      panelVm: this,
      savedConfig: null, // 提交表单时组织生成的对象，用于父组件收集子组件的配置
      timers: {}, // 组件配置界面中的计时器，需要在beforeDestory中清除掉，防止切换页面或组件被销毁后还继续执行
    };
  },
  computed: {
    ...mapState({
      panelConfigs: state => state.VisualComponentsModule.panelConfigs,
      saveAllDataProcess: state => state.VisualComponentsModule.saveAllDataProcess,
    }),
    panelConfig() {
      const emptyConfig = {
        siteId: '',
        property: {},
        widgetInstanceId: '',
        data: {
          tableData: [],
        },
        events: {},
      };
      return this.panelConfigs[this.widgetInstanceId] || emptyConfig;
    },
    propertyLabel() {
      let label;
      if (window._adoPremise.uc.theme === 'light') {
        label = this.$demoi18n('panel.tab.property');
      } else {
        label = this.$demoi18n('panel.tab.propertyDark');
      }
      return label;
    },
  },
  provide() {
    return {
      configPanelRefs: this.$refs?.commonConfigPanel?.$refs || this.$refs,
      widgetInstanceId: this.widgetInstanceId,
      isChildComponent: this.isChildComponent,
      panelWid: this.widgetInstanceId,
      getPanelVm: () => this,
    };
  },
  methods: {
    ...mapMutations(['setState', 'setPanelConfig', 'delPanelConfig', 'delPanelApiData']),

    // 多个vapp同时加载时，全局组件VsFormItem会互相覆盖，需要覆盖回来
    initVsFormItem() {
      window.xVueWeb.app.component('VsFormItem', VsFormItem);
    },
    initPanelVm() {
      this.panelVm = this.$refs.commonConfigPanel || this;
    },

    // 设置当前预览面选中的组件，用于配置面板和预览组件之前交互
    initPreviewVm() {
      EventBus.$emit(`curPreviewVm_${this.widgetInstanceId}`);
    },

    // 子组件保存配置
    async saveChildComps() {
      const compVms = this.$refs.childComps || [];
      const ps = compVms.map(n => {
        const panelVm = n.$refs.commonConfigPanel || n;
        return new Promise(async resolve => {
          const res = await panelVm.saveAllData();
          resolve(res);
        });
      });
      const arr = await Promise.all(ps);
      const isTrue = arr.every(n => n);
      return isTrue;
    },

    async saveAllData() {
		// debugger
      this.savedConfig = null;

      // 初始化保存条件
      this.isCanSave = true;

      // 先保证数据都加载完毕
      this.checkLoading();
      if (!this.isCanSave) {
        return false;
      }

      // 先测其他value-inputer字段，该方法内部重新触发saveAllData
      if (!this.isChildComponent) {
        const otherCheck = this.checkValidOthers();
        if (!otherCheck) {
          return false;
        }
      }

      const panelCheck = await this.checkValid();
      if (!panelCheck) {
        return false;
      }

      // 子组件配置保存
      const childrenSaved = await this.saveChildComps();
      if (!childrenSaved) {
        return false;
      }

      const config = this.collectCompConfig();
      this.updateEmitParamsObj(config.events);

      if (window.parent.saveVmConfig && !this.isChildComponent) {
        setTimeout(() => {
          window.parent.saveVmConfig(config);
        }, 50);
      }

      if (!this.isCanSave) {
        return false;
      }

      if (this.isChildComponent) {
        this.savedConfig = config;
        return true;
      }

      this.saveProperties(config);
      visualAction('saveAllData', 3000);
      return true;
    },

    getLinkage() {
      let linkage = [];
      if (this.panelVm.$refs.panel_linkage) {
        if (this.panelVm.$refs.panel_linkage.data && this.panelVm.$refs.panel_linkage.data.length) {
          linkage = this.panelVm.$refs.panel_linkage.data;
        } else {
          const { fixedEvents, showEvents, hideEvents } = this.panelVm.$refs.panel_linkage;
          linkage = fixedEvents.concat(showEvents).concat(hideEvents);
        }
      }

      // 删除多余的事件项目，减少保存到数据库的事件数量
      linkage = linkage.filter(n => n.key);

      // 删除可能出现的xvue设置的evt.callBack
      linkage = JSON.parse(JSON.stringify(linkage));
      linkage.forEach(n => {
        delete n.callBack;
      });
      return linkage;
    },

    getAdvancedLinkage() {
      let advancedLinkage = {};
      const panelLinkageVm = this.panelVm.$refs.panel_linkage;
      if (panelLinkageVm) {
        advancedLinkage = panelLinkageVm.config.advancedLinkage || {};
      }
      return advancedLinkage;
    },

    getInitiative() {
      let initiative = this.panelVm.$refs?.panel_linkage?.$refs.lowCodeLikage?.initiative;

      // 删除临时字段
      if (initiative) {
        initiative = JSON.parse(JSON.stringify(initiative));
        initiative.actions.forEach(n => {
          delete n.elSelectorVal;
          n.subActions.forEach(n1 => {
            delete n1.isParamsVisible;
          });
        });
      }
      return initiative;
    },

    collectIcons(obj, icons = []) {
      if (!isArray(obj) && !isObject(obj)) {
        return;
      }

      if (isArray(obj)) {
        obj.forEach(n => {
          this.collectIcons(n, icons);
        });
      }

      if (isObject(obj)) {
        if (obj.icon_id) {
          if (obj.type === 'serverImg') {
            icons.push(obj);
          }
        } else {
          Object.entries(obj).forEach(([key, val]) => {
            this.collectIcons(val, icons);
          });
        }
      }
    },

    collectIconIds(icons) {
      const libIds = [];
      const notLibIds = [];
      icons.forEach(n => {
        if (n.isLibImg) {
          libIds.push(n.icon_id);
        } else {
          notLibIds.push(n.icon_id);
        }
      });
      return {
        useImageLibraryAllList: libIds,
        useImageAllList: notLibIds,
      };
    },

    // 更新config 中event 包含 EMIT_PARAMS_OBJ 的 parameters
    updateEmitParamsObj(linkage) {
      if (!linkage) {
        return;
      }
      linkage.forEach(event => {
        if (event.type === 'out') {
          event.parameters.forEach(parameter => {
            if (parameter.key.indexOf(EMIT_PARAMS_OBJ) > -1) {
              parameter.key = `${EMIT_PARAMS_OBJ}_${this.widgetInstanceId}`;
            }
          });
        }
      });
    },

    // 通过xvue 的事件将配置保存到xvue数据库中
    saveProperties(config) {
      // 兼容原来传参格式
      const property = config.property || config.config.property;
      const data = config.data || config.config?.data;
      const linkage = config.linkage || config.events;
      const { advancedLinkage, components, initiative, imageUsed } = config;
      const map = config.map || config.config?.map;

      this.config.config = {
        property,
      };
      if (data) {
        this.config.config.data = data;
      }
      if (map) {
        this.config.config.map = map;
      }
      this.config.events = linkage;
      this.config.advancedLinkage = advancedLinkage;
      this.config.imageUsed = imageUsed;
      if (components) {
        this.config.components = components;
      }
      this.config.initiative = initiative;

      // 在这里，处理数据配置提升
      this.upscaleDataConfig();

      if (window.saveProperties) {
        window.saveProperties(this.config);
      }

      EventBus.$emit(`save_properties_${this.widgetInstanceId}`, this.config);
    },

    // 将组件的config里的所有数据配置提升
    upscaleDataConfig() {
      this.config.dataSources = [];
      let index = 1;
      // 将组件可能存在的数据配置列举出来并提升
      if (this.config.config.data) {
        this.config.dataSources.push({index, ...this.config.config.data});
        index++;
      }
      // 高级tooltip设置里的数据配置
      if (this.config.config.property.tooltip?.apis?.length) {
        const apis = this.config.config.property.tooltip?.apis;
        for (let i = 0; i < apis.length; i++) {
          const api = apis[i];
          this.config.dataSources.push({index, ...this.config.config.data});
          index++;
        }
      }
    },

    // 检查数据页签配置字段是否为空
    checkConfigData(data) {
      const { tableData } = data;
      tableData.forEach(item => {
        if (this.isCanSave) {
          if (!item.skipVerification) {
            if (!item.mapping) {
              this.isCanSave = false;
              this.$message({
                message: `${this.$demoi18n('message.mappingFieldEmpty')} : ${item.field}`,
                type: 'warning',
              });
            }
          }
        }
      });
    },

    // 检查各页签的loading状态
    checkLoading() {
      const isLoadingProperty = this.panelVm.$refs.panel_property?.isLoading;
      const isLoadingData = this.panelVm.$refs.panel_data?.isLoading;
      const isLoadingLinkage = this.panelVm.$refs.panel_linkage?.isLoading;

      // 有一个没loading完的话不让提交
      if (isLoadingProperty || isLoadingData || isLoadingLinkage) {
        this.isCanSave = false;
        this.$message({
          message: this.$demoi18n('message.dataLoadingPlsWait'),
          type: 'warning',
        });
      }
    },

    // 获取xvue基本信息组件的相关内容
    getXVueBaseInfo() {
      const xVueBaseInfo = this.panelVm.$refs.xVueBaseInfo;
      let useSharedConfig = false; // 是否有用共享配置/关联配置
      const xVueBaseInfoCanSave = true; // xvue 基本信息能否保存
      if (xVueBaseInfo) {
        // 是否用的默认配置来修改，保存
        const { isSharedConfig, isLinkConfig } = xVueBaseInfo;

        if (isSharedConfig) {
          useSharedConfig = true;
        } else if (isLinkConfig) {
          useSharedConfig = true;
        } else {}
      }
      return {
        xVueBaseInfo,
        useSharedConfig,
        xVueBaseInfoCanSave,
      };
    },

    // 提交前先执行内部检查方法
    checkValid() {
      const panels = {
        property: 'first',
        data: 'second',
        linkage: 'third',
      };
      const arr = [];
      Object.entries(panels).map(([i]) => {
        const panel = this.panelVm.$refs[`panel_${i}`];
        if (panel && panel.check) {
          let p = panel.check(this);
          if (!isPromise(p)) {
            p = new Promise(resolve => resolve(p));
          }
          p.tabKey = panels[i];
          arr.push(p);
        }
      });

      return Promise.all(arr)
        .then(data => {
          for (let i = 0; i < data.length; i++) {
            if (data[i] === false) {
              this.activeName = arr[i].tabKey;
              return false;
            }
            if (typeof data[i] === 'object') {
              this.activeName = arr[i].tabKey;
              let res = true;
              Object.entries(data[i]).map(([key]) => {
                if (isArray(data[i][key]) && data[i][key][0]?.message) {
                  $message({
                    message: data[i][key][0].message,
                    type: 'error',
                  });
                  res = false;
                }
              });
              return res;
            }
          }
          return true;
        })
        .catch(e => {
          window.showErr(e);
        });
    },

    // 校验其他字段
    checkValidOthers() {
      if (!this.saveAllDataProcess.isChecking) {
        this.setState({
          saveAllDataProcess: {
            errors: [],
            isChecking: true,
          },
        });
        setTimeout(async() => {
          await this.saveAllData();
        }, 100);
        return false;
      } else {
        this.setState({
          saveAllDataProcess: {
            ...this.saveAllDataProcess,
            isChecking: false,
          },
        });
        if (this.saveAllDataProcess.errors.length) {
          return false;
        }
        return true;
      }
    },

    /*
     * 组件config国际化修正
     * 因为保存在config里面，切换语言后，国际化还是之前语言的显示，需要手工修正
     */
    updateConfigI18n() {
      // customCalculationXTag.option_label 修正
      const xtagItem =
        this.config.config &&
        this.config.config.data &&
        this.config.config.data.customCalculationXTag &&
        this.config.config.data.customCalculationXTag[0];
      if (xtagItem) {
        let label = xtagItem.option_label;
        switch (xtagItem.type) {
          case 'add':
            label = this.$demoi18n('word.addCustomCalculation');
            break;
          default:
            break;
        }
        xtagItem.option_label = label;
      }
    },

    // 属性，数据，事件配置集合，存放在vuex，解决跨面板数据访问
    initPanelConfig(tryTimes = 5) {
      const propertyVm = this.panelVm.$refs.panel_property;
      const dataVm = this.panelVm.$refs.panel_data;
      const linkageVm = this.panelVm.$refs.panel_linkage;

      if (window.visualComp.initPanelConfigLocked) { // 子组件优先
        clearTimeout(this.timers.initPanelConfig);
        delete window.visualComp.initPanelConfigLocked;
        return;
      }

      if ((!propertyVm || !dataVm) && tryTimes > 0) {
        clearTimeout(this.timers.initPanelConfig);
        this.timers.initPanelConfig = setTimeout(() => {
          this.initPanelConfig(tryTimes - 1);
        }, 500);
        return;
      }

      const property = propertyVm?.form || {};
      const data = dataVm?.form || {};

      let events = [];
      if (linkageVm) {
        const { fixedEvents, showEvents, hideEvents } = linkageVm;
        events = fixedEvents.concat(showEvents).concat(hideEvents);
      }

      const curPanelConfig = {
        siteId: this.$route.params.siteId,
        widgetInstanceId: this.widgetInstanceId,
        property,
        data,
        events,
      };
      this.setPanelConfig(curPanelConfig);
    },

    // 销毁面板内存引用，防止内存溢出
    clearPanelConfig() {
      this.delPanelConfig(this.widgetInstanceId);
    },

    // 清除面板api数据，节省内存
    clearPanelApiData() {
      this.delPanelApiData(this.widgetInstanceId);
    },

    // 检查config中events的更新，用于补全后来才增加的发出事件
    updateConfigEvents() {
      if (!this.config?.events?.[0]) {
        return;
      }
      const firstEvnet = this.config.events[0];
      const firstEvnetOrg = this.orgConfig.events[0];
      if (!firstEvnet || !firstEvnetOrg) {
        return;
      }
      if (firstEvnet.type === 'in' && firstEvnetOrg.type === 'out') {
        this.config.events.unshift(firstEvnetOrg);
      }
    },

    getChildCompsConfigs() {
      if (!this.config.components) {
        return false;
      }
      const childVms = this.$refs.childComps || [];
      const configs = clone(this.config.components);
      childVms.forEach((n, i) => {
        const panelVm = n.$refs.commonConfigPanel || n;
        const compId = n.widgetInstanceId.replace(/.*_child_(.*)$/, '$1');
        configs.find(n1 => String(n1.id) === compId).config = panelVm.savedConfig;
      });
      return configs;
    },

    // 收集组件配置信息
    collectCompConfig() {
      const propertyVm = this.panelVm.$refs.panel_property;
      const dataVm = this.panelVm.$refs.panel_data;

      // 属性页签数据
      const property = propertyVm?.form || {};

      // 数据页签数据
      let data = this.config.config.data || {};
      if (dataVm) {
        data = dataVm.form;

        // 数据页签增加xtag的自定义计算
        const panelDataCommon = this.panelVm.$refs.panel_data.$refs.panelDataCommon;
        if (panelDataCommon && panelDataCommon.customCalculationXTag) {
          data.customCalculationXTag = panelDataCommon.customCalculationXTag;
        }
      }

      // 事件联动
      const events = this.getLinkage();

      // 高级事件联动
      const advancedLinkage = this.getAdvancedLinkage();

      // 主动触发事件
      const initiative = this.getInitiative();

      // 子组件
      const components = this.getChildCompsConfigs() || null;

      // 图标收集
      const icons = [];
      this.collectIcons(property, icons);
      this.collectIcons(components, icons);
      const imageUsed = this.collectIconIds(icons);

      const config = {
        ...this.orgConfig,
        config: {
          property,
          data,
        },
        events,
        advancedLinkage,
        initiative,
        imageUsed,
      };
      if (components) {
        config.components = components;
      }

      return config;
    },

    // 添加洞察云样式名
    initBoxClassName() {
      this.$el.classList.add(this.visualThemeClassName);
    },

    // 计算编排面板的高度，保证保存按钮位置在右下
    initPanelHeight() {
      setTimeout(() => {
        const panelEl = this.$el;
        const { top } = panelEl.getBoundingClientRect();
        panelEl.style.height = `calc(100vh - ${top}px - 100px)`; // 减去顶部距离和保存按钮高度
      }, 200);
    },
    fixConfig() {
      const dbConfig = window.isLocalEnv ? this.config : this.dbConfig;
      if (!dbConfig) {
        return;
      }
      const _config = configMerge.mergeConfig(this.orgConfig, dbConfig);
      Object.entries(this.config).map(([i]) => {
        this.config[i] = _config[i];
      });
    },
    initPanelActiveTab() {
      if (!this.$refs.xVueBaseInfo) {
        this.activeName = 'first';
      }
    },

    // 销毁组件中的setTimerout延时任务
    clearTimers() {
      Object.entries(this.timers).map(([i]) => {
        clearTimeout(this.timers[i]);
      });
    },

    // 配置面板显隐绑定
    bindVisibleChange() {
      bindVisibleChange(
        this.$el,
        () => {
          clearTimeout(this.timers.visibleChange);
          this.timers.visibleChange = setTimeout(() => {
            this.initPanelConfig();
            this.initPreviewVm();
          }, 50);
        },
        () => {
          window.visualComp.curPreviewVm = null;
        },
      );
    },

    // 判断编排还是预览，暂时用于low-code-util
    initDesignView() {
      window.visualComp.isDesignView = true;
    },

  },
  created() {
    EventBus.$on(`save_properties_success${this.widgetInstanceId}`, () => {
      EventBus.clear(`saveBaseInfo_${this.widgetInstanceId}`);
      EventBus.$emit(`saveBaseInfo_${this.widgetInstanceId}`);
    });

    this.initVsFormItem();
    this.fixConfig();
    this.updateConfigI18n();
    this.updateConfigEvents();
    this.initDesignView();
  },
  mounted() {
    this.bindVisibleChange();
    this.initPanelConfig();
    this.initBoxClassName();
    this.initPanelHeight();
    this.initPanelActiveTab();
    if (window.isLocalEnv) {
      // 本地开发环境添加配置面板应用快捷键   空格+ctrl
      document.addEventListener('keyup', event => {
        if (event.keyCode === 32 && event.ctrlKey) {
          this.saveAllData();
        }
      });
    }
  },
  beforeUnmount() {
    this.clearPanelConfig();
    this.clearPanelApiData();
    this.clearTimers();
    if (this.widgetInstanceId) {
      EventBus.$off(`save_properties_success${this.widgetInstanceId}`);
    }
  },
};
